import numpy as np
import math
from skimage.transform import resize
import scipy.ndimage
import matplotlib.pyplot as plt
"""
# Downsample using order 8 Chebyshev type I filter
def downsample(data):
    return scipy.signal.decimate(data, 6, axis = 0)
"""
def prepare_data(mat):
    # Left footstep
    dataL = mat['dataL']
    # Right footstep
    dataR = mat['dataR']  
    return (dataL, dataR)

def calGRF(data):
    return np.add.accumulate(data)


def process_foot(data):
    Tmax = 1600
    data = data[:Tmax]
    grf = calGRF(data)
    s_avg = data.mean(axis = 1)
    s_upper = np.max(data, axis = 1)
    s_lower = np.min(data, axis = 1)
    grf_t = grf.mean(axis = 1)
    #s_range = s_upper - s_lower
    #s_std = np.std(data, axis = 1)
    #s_grad = np.gradient(s_avg)

    processed = np.append(s_avg, [
        grf_t,
        s_upper,
        s_lower,
        #s_range,
        #s_std,
        #s_grad
    ])
        
    return processed

def process_matlab(mat):
    dataL, dataR = prepare_data(mat)
    footL, footR = process_foot(dataL), process_foot(dataR)
    #processed = np.append(footL, [footR, footL - footR])
    processed = np.append(footL, footR)
    return processed

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

import os
import scipy.io
import scipy.signal

"""
index_files_path = 'D:/A_SEU/SFBD/IndexFiles/'
data_files_path = 'D:/A_SEU/SFBD/SFootBD/'
"""

index_files_path = 'D:/A_SEU/SFBD/IndexFiles/B3/'
data_files_path = 'D:/A_SEU/SFBD/SFootBD/'


train_list_file = index_files_path + 'LstTrain'
imposter_list_file = index_files_path + 'LstImp'
test_evaluation_list_file = index_files_path + 'LstTestEvaluation'
test_validation_list_file = index_files_path + 'LstTestValidation'



def load_features(filename):
    mat_file = os.path.join(data_files_path, filename + '.mat')
    mat = scipy.io.loadmat(mat_file)
    return process_matlab(mat)

def load_data_file(index_file):
    return pd.read_csv(index_file, sep = ' ', header = None)

def load_dataset(data_list, clients):    
    X = []
    y = []
    
    for item in data_list.itertuples():
        X_item = load_features(item[2])
        y_item = item[1]
        
        matches = np.where(clients == y_item)[0]
        
        X.append(X_item)
        # clients.shape[0] becomes imposter class
        y.append(matches[0] if matches.shape[0] != 0 else clients.shape[0])
        
    return np.array(X), np.array(y)

train_index = load_data_file(train_list_file)

#np.unique(train_index[0], return_counts=True)

clients = np.unique(train_index[0])

X_train, y_train = load_dataset(train_index, clients)

plt.plot(X_train[0])

imposter_index = load_data_file(imposter_list_file)
X_imposter, y_imposter = load_dataset(imposter_index, clients)

X_train = np.append(X_train, X_imposter, axis = 0)
y_train = np.append(y_train, y_imposter, axis = 0)
val_index = load_data_file(test_validation_list_file)
#np.unique(np.isin(val_index[0], clients), return_counts=True)
#np.unique(val_index[0][np.isin(val_index[0], clients)], return_counts=True)
eval_index = load_data_file(test_evaluation_list_file)
#np.unique(np.isin(eval_index[0], clients), return_counts=True)



X_test, y_test = load_dataset(eval_index, clients)

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.multiclass import OneVsRestClassifier
#from sklearn.linear_model import SGDClassifier

model = Pipeline([
    ("std_scaler", StandardScaler()),
    #("model", OneVsRestClassifier(SVC(kernel='rbf')))
    ("model", SVC(kernel='rbf', C=7, gamma=1))
    #("model", SGDClassifier())
])

from sklearn.utils import shuffle
X_train, y_train = shuffle(X_train, y_train)

model.fit(X_train, y_train)
y_pred = model.predict(X_test)

from sklearn.metrics import accuracy_score

acc = accuracy_score(y_test, y_pred)
print(acc)

imposter_class = clients.shape[0]

fp = np.logical_and(y_pred != imposter_class, y_pred != y_test)
fp = np.where(fp)[0].shape[0]

fn = np.logical_and(y_pred == imposter_class, y_test != imposter_class)
fn = np.where(fn)[0].shape[0]

cnt = y_test.shape[0]
far = fp / cnt
frr = fn / cnt

print (far, frr)
